package com.tianlang.annotation;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import com.jfinal.kit.StrKit;
import com.jfinal.log.Log;
import com.jfinal.plugin.activerecord.ActiveRecordPlugin;
import com.jfinal.plugin.activerecord.Model;

/**
 * 自动绑定（来自jfinal ext) 加入ModelBind的 获取 key
 * 
 * @author mcp
 *
 */
public class AutoBindModels {

	protected final Log logger = Log.getLog(AutoBindModels.class);

	private String configName = "main";

	private ActiveRecordPlugin arp;

	@SuppressWarnings("rawtypes")
	private List<Class<? extends Model>> excludeClasses = new ArrayList<Class<? extends Model>>();

	private List<String> includeJars = new ArrayList<String>();

	public AutoBindModels(ActiveRecordPlugin arp) {
		this.arp = arp;
		config();
	}

	public AutoBindModels(String configName, ActiveRecordPlugin arp) {
		this.configName = configName;
		this.arp = arp;
		config();
	}

	public AutoBindModels addJar(String jarName) {
		if (StrKit.notBlank(jarName)) {
			includeJars.add(jarName);
		}
		return this;
	}

	public AutoBindModels addJars(String jarNames) {
		if (StrKit.notBlank(jarNames)) {
			addJars(jarNames.split(","));
		}
		return this;
	}

	public AutoBindModels addJars(String[] jarsName) {
		includeJars.addAll(Arrays.asList(jarsName));
		return this;
	}

	public AutoBindModels addJars(List<String> jarsName) {
		includeJars.addAll(jarsName);
		return this;
	}

	@SuppressWarnings("rawtypes")
	public AutoBindModels addExcludeClass(Class<? extends Model> clazz) {
		if (clazz != null) {
			excludeClasses.add(clazz);
		}
		return this;
	}

	@SuppressWarnings("rawtypes")
	public AutoBindModels addExcludeClasses(Class<? extends Model>[] clazzes) {
		excludeClasses.addAll(Arrays.asList(clazzes));
		return this;
	}

	@SuppressWarnings("rawtypes")
	public AutoBindModels addExcludeClasses(List<Class<? extends Model>> clazzes) {
		excludeClasses.addAll(clazzes);
		return this;
	}

	@SuppressWarnings({ "rawtypes", "unchecked" })
	public void config() {
		// List<Class<? extends Model>> modelClasses =
		// ClassSearcher.findInClasspathAndJars(Model.class, includeJars);
		List<Class<? extends Model>> modelClasses = ClassSearcher.findInClasspath(Model.class);
		ModelBind modelBind = null;
		for (Class model : modelClasses) {
			if (excludeClasses.contains(model)) {
				continue;
			}
			modelBind = (ModelBind) model.getAnnotation(ModelBind.class);
			if (modelBind == null || StrKit.isBlank(modelBind.table())) {
				continue;
			}
			String config = modelBind.configName();
			// all default ,so not null
			if (StrKit.isBlank(config) || StrKit.isBlank(configName)) {
				logger.error("routes.add is null");
				continue;
			}
			// join many database support
			if (configName.equals(config)) {
				arp.addMapping(modelBind.table(), modelBind.key(), model);
				logger.debug(
						config + " --> routes.add(" + model + "," + modelBind.table() + ", " + modelBind.key() + ")");
			}

		}
	}

	@SuppressWarnings("rawtypes")
	public List<Class<? extends Model>> getExcludeClasses() {
		return excludeClasses;
	}

	@SuppressWarnings("rawtypes")
	public void setExcludeClasses(List<Class<? extends Model>> excludeClasses) {
		this.excludeClasses = excludeClasses;
	}

	public List<String> getIncludeJars() {
		return includeJars;
	}

	public void setIncludeJars(List<String> includeJars) {
		this.includeJars = includeJars;
	}

}
